#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "list.h"
#include "msg_queue_peer.h"
#include "cJSON.h"
#include <sys/types.h>
#include <sys/wait.h>
#include "shmem.h"

#define PORT 8888
#define BUFFER_SIZE 1024

// 消息队列结构体
struct que_order
{
    long tag;     // 消息队列的设备类型
    int key;      // 数据节点唯一标识
    char val[32]; // 数据
};

// 共享内存结构体
union val_t
{
    int b_val;   // bool类型存储空间
    int i_val;   // 整形值存储空间
    float f_val; // 浮点值存储空间
};

struct mb_node
{
    int key;             // 唯一键值
    int type;            // 数据点类型
    int dev_type;        // 数据点属于哪个设备，根据网关支持的设备自行定义
    union val_t old_val; // 变化上报后需要更新旧值
    union val_t new_val; // 从共享内存取出最新数据，放到new_val中
    int ret;             // 默认为-1，采集成功后设置为0，采集失败再置-1
};
// 全局变量区
char shared_memory[32];
struct que_order msg;
struct shm_param para;
int *Count;
char temp[32];
char humi[32];
char fan[32];
char motor[32];
char led_pwm[32];
char fire[32];

// 控制命令下发序列化函数
char *serializeJSON(const char *dev, const char *val)
{
    cJSON *root = cJSON_CreateObject();
    cJSON_AddStringToObject(root, "dev", dev);
    cJSON_AddStringToObject(root, "val", val);
    char *jsonStr = cJSON_Print(root);
    cJSON_Delete(root);
    return jsonStr;
}

// 上报处理函数
void Report(int clientSocket)
{    int i=1;
    char buffer[BUFFER_SIZE];
    while (1)
    {
        printf("上报进程运行中");
        ssize_t bytesRead = recv(clientSocket, buffer, BUFFER_SIZE - 1, 0);
        if (bytesRead <= 0)
        {
            perror("接收错误或客户端断开连接");
            break;
        }
        buffer[bytesRead] = '\0';
        printf("接收成功：收到数据,嗨嗨嗨:%s\n", buffer);
        
        printf("%d\n",i++);
        // 数据处理

        cJSON *root = cJSON_Parse(buffer);

        cJSON *dataArray = cJSON_GetObjectItem(root, "data");
        // *Count = cJSON_GetArraySize(dataArray);
        for (int i = 0; i < 6; i++)
        {
            cJSON *itemJSON = cJSON_GetArrayItem(dataArray, i);
            cJSON *nameJSON = cJSON_GetObjectItem(itemJSON, "name");
            cJSON *valJSON = cJSON_GetObjectItem(itemJSON, "val");
            if (!strcmp(nameJSON->valuestring, "temp"))
            {
                strcpy(temp, valJSON->valuestring);
            }
            else if (!strcmp(nameJSON->valuestring, "humi"))
            {
                strcpy(humi, valJSON->valuestring);
            }
            else if (!strcmp(nameJSON->valuestring, "fan"))
            {
                strcpy(fan, valJSON->valuestring);
            }
            else if (!strcmp(nameJSON->valuestring, "motor"))
            {
                strcpy(motor, valJSON->valuestring);
            }
            else if (!strcmp(nameJSON->valuestring, "led_pwm"))
            {
                strcpy(led_pwm, valJSON->valuestring);
            }
            else if (!strcmp(nameJSON->valuestring, "fire"))
            {
                strcpy(fire, valJSON->valuestring);
            }
            else
            {
            }
        }
        cJSON_Delete(root);
        // 读取共享内存
        int rec = shm_init(&para, "five", 1024);
        if (rec == -1)
        {
            perror("共享内存初始化失败");
        }
        int *num = shm_getaddr(&para);
        if (NULL == num)
        {
            perror("获取共享内存失败");
        }
        struct mb_node *node;
        node = (struct mb_node *)num + 1;
        for (int j = 0; j < *num; j++)
        {
            if ((node + j)->key == 301) // 温度值
            {
                (node + j)->new_val.f_val = atof(temp);
                (node + j)->type = 3;
                (node + j)->ret = 0;
            }
            if ((node + j)->key == 302) // 湿度值
            {
                (node + j)->new_val.f_val = atof(humi);
                (node + j)->type = 3;
                (node + j)->ret = 0;
            }
            if ((node + j)->key == 303) // 空气净化器
            {
                (node + j)->new_val.i_val = atoi(fan);
                (node + j)->type = 1;
                (node + j)->ret = 0;
            }
            if ((node + j)->key == 304) // 除湿器
            {
                (node + j)->new_val.i_val = atoi(motor);
                (node + j)->type = 1;
                (node + j)->ret = 0;
            }
            if ((node + j)->key == 305) // 灯
            {
                (node + j)->new_val.i_val = atoi(led_pwm);
                (node + j)->type = 1;
                (node + j)->ret = 0;
            }
            if ((node + j)->key == 306) // 火警
            {
                (node + j)->new_val.i_val = atoi(fire);
                (node + j)->type = 1;
                (node + j)->ret = 0;
            }
        }
    }

    close(clientSocket);
}

// 命令下达函数
void Command(int clientSocket)
{
    char command_dev[32] = "";
    while (1)
    {

        // 读取消息队列数据
        if (msg_queue_recv("five", &msg, sizeof(struct que_order), 3, 0) == -1)
        {
            perror("读取消息队列错误");
            break;
        }
        else
        {
            printf("读取消息队列成功\n");
            // 判断控制哪个设备
            switch (msg.key)
            {
            case 303:
                strcpy(command_dev, "fan");
                break;
            case 304:
                strcpy(command_dev, "motor");
                break;
            case 305:
                strcpy(command_dev, "led_pwm");
                break;
            default:
                printf("未知的 key 值：%d\n", msg.key);
                break;
            }
            // 将数据序列化后放入发送缓存区
            char *message;
            message = serializeJSON(command_dev, msg.val);
            ssize_t byteSent = send(clientSocket, message, strlen(message), 0);
            if (byteSent <= 0)
            {
                perror("发送错误");
            }
            printf("发送成功：已发送消息 %s\n", message);
            // 释放序列化后动态分配的内存
            free(message);
            memset(command_dev, 0, sizeof(command_dev));
        }
    }
}

int main()
{
    int serverSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (serverSocket == -1)
    {
        perror("创建套接字失败");
        return -1;
    }

    // 设置地址可重用选项
    int optval = 1;
    if (setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1)
    {
        perror("设置套接字选项失败");
        close(serverSocket);
        return -1;
    }

    struct sockaddr_in serverAddress;
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_addr.s_addr = INADDR_ANY;
    serverAddress.sin_port = htons(PORT);

    if (bind(serverSocket, (struct sockaddr *)&serverAddress, sizeof(serverAddress)) == -1)
    {
        perror("绑定失败");
        close(serverSocket);
        return -1;
    }

    if (listen(serverSocket, 5) == -1)
    {
        perror("监听失败");
        close(serverSocket);
        return -1;
    }

    printf("服务器正在监听端口 %d...\n", PORT);

    int clientSocket = accept(serverSocket, NULL, NULL);
    if (clientSocket == -1)
    {
        perror("接受连接失败");
        close(serverSocket);
        return -1;
    }

    printf("连接成功！客户端已连接。\n");

    pid_t pid = fork();
    if (pid == 0)
    {
        Report(clientSocket);
    }
    else
    {
        Command(clientSocket);
    }

    // 等待子进程结束并清理资源
    int status;
    waitpid(pid, &status, 0);

    close(clientSocket);
    close(serverSocket);

    return 0;
}
